package com.matt.sooncleaner.junk.step

import com.blankj.utilcode.util.StringUtils
import com.cloud.cleanjunksdk.ad.AdvBean
import com.cloud.cleanjunksdk.cache.CacheBean
import com.cloud.cleanjunksdk.filescan.ApkBean
import com.cloud.cleanjunksdk.filescan.LogBean
import com.cloud.cleanjunksdk.filescan.TmpBean
import com.cloud.cleanjunksdk.residual.ResidualBean
import com.cloud.cleanjunksdk.task.Clean
import com.cloud.cleanjunksdk.task.JunkScanCallback
import com.cm.plugincluster.junkengine.junk.bean.MediaFile
import com.cm.plugincluster.junkengine.junk.engine.MEDIA_TYPE
import com.matt.sooncleaner.R
import com.matt.sooncleaner.junk.AppCacheBean
import com.matt.sooncleaner.junk.JunkBean
import com.matt.sooncleaner.junk.JunkChildBean


abstract class JunkScanStep<T> {
    private var mSize = 0L
    private var mJunkName = ""
    val junkBean = JunkBean()
    init {
        junkBean.name = getJunkName()
    }

    abstract fun startScan(cleanSdk: Clean, callback: JunkScanCallback)

    abstract fun cancelScan(cleanSdk: Clean)

    abstract fun getJunkName(): String

    fun getSize() = mSize

    open fun onUpdateScan(bean: T) {}

    open fun onUpdateMediaScan(bean: T, mediaType: MEDIA_TYPE) {}

    open fun getMediaType(): MEDIA_TYPE? = null
}

class AdJunkScanStep: JunkScanStep<AdvBean>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startAdScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelAdScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.ad_junk)
    override fun onUpdateScan(bean: AdvBean) {
        val junkChildBean = JunkChildBean()
        junkChildBean.path = bean.path
        junkChildBean.size = bean.size
        junkChildBean.name = bean.name
        junkBean.addChildBean(junkChildBean)
        junkBean.size += junkChildBean.size
    }

}

class ApkJunkScanStep: JunkScanStep<ApkBean>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startAPKScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelAPKScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.apk_junk)

    override fun onUpdateScan(bean: ApkBean) {
        val junkChildBean = JunkChildBean()
        junkChildBean.path = bean.path
        junkChildBean.size = bean.size
        junkChildBean.name = bean.name
        junkBean.addChildBean(junkChildBean)
        junkBean.size += junkChildBean.size
    }
}

class AppCacheJunkScanStep: JunkScanStep<CacheBean>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startAppCacheScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelAppCacheScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.app_cache_junk)

    override fun onUpdateScan(bean: CacheBean) {
        val junkChildBean = JunkChildBean()
        junkChildBean.size = bean.size
        junkChildBean.name = bean.appName
        junkChildBean.isAppCache = true
        junkBean.size += bean.size
        junkBean.addChildBean(junkChildBean)
        for (pathBean in bean.pathBeen) { // there can be many cache junk files for one app
            val desc_name: String = pathBean.cacheJunkDesc // cache description
            val path: String = pathBean.cleanPath // cache path
            val sizeP: Long = pathBean.size // cache size
            val appCacheBean = AppCacheBean()
            appCacheBean.name = desc_name
            appCacheBean.path = path
            appCacheBean.isDeep = pathBean.isDeep
            appCacheBean.size = sizeP
            junkChildBean.appCacheBeens.add(appCacheBean)
        }
    }
}

class DocJunkScanStep: JunkScanStep<MediaFile>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startDocScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelDocScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.doc)

    override fun onUpdateMediaScan(bean: MediaFile, mediaType: MEDIA_TYPE) {
        super.onUpdateMediaScan(bean, mediaType)
        if (mediaType == MEDIA_TYPE.DOC) {
            val junkChildBean = JunkChildBean()
            junkChildBean.path = bean.path
            junkChildBean.size = bean.size
            junkChildBean.name = bean.title
            junkBean.size += junkChildBean.size
            junkBean.addChildBean(junkChildBean)
        }
    }

    override fun getMediaType(): MEDIA_TYPE = MEDIA_TYPE.DOC
}

class PhotoJunkScanStep: JunkScanStep<MediaFile>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startPhotoScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelDocScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.photo)

    override fun onUpdateMediaScan(bean: MediaFile, mediaType: MEDIA_TYPE) {
        super.onUpdateMediaScan(bean, mediaType)
        if (mediaType == MEDIA_TYPE.PHOTO) {
            val junkChildBean = JunkChildBean()
            junkChildBean.path = bean.path
            junkChildBean.size = bean.size
            junkChildBean.name = bean.title
            junkBean.size += junkChildBean.size
            junkBean.addChildBean(junkChildBean)
        }
    }

    override fun getMediaType(): MEDIA_TYPE = MEDIA_TYPE.PHOTO
}

class VideoJunkScanStep: JunkScanStep<MediaFile>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startVideoScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelDocScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.video)

    override fun onUpdateMediaScan(bean: MediaFile, mediaType: MEDIA_TYPE) {
        super.onUpdateMediaScan(bean, mediaType)
        if (mediaType == MEDIA_TYPE.VIDEO) {
            val junkChildBean = JunkChildBean()
            junkChildBean.path = bean.path
            junkChildBean.size = bean.size
            junkChildBean.name = bean.title
            junkBean.size += junkChildBean.size
            junkBean.addChildBean(junkChildBean)
        }
    }

    override fun getMediaType(): MEDIA_TYPE = MEDIA_TYPE.VIDEO
}

class AudioJunkScanStep: JunkScanStep<MediaFile>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startAudioScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelDocScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.audio)

    override fun onUpdateMediaScan(bean: MediaFile, mediaType: MEDIA_TYPE) {
        super.onUpdateMediaScan(bean, mediaType)
        if (mediaType == MEDIA_TYPE.AUDIO) {
            val junkChildBean = JunkChildBean()
            junkChildBean.path = bean.path
            junkChildBean.size = bean.size
            junkChildBean.name = bean.title
            junkBean.size += junkChildBean.size
            junkBean.addChildBean(junkChildBean)
        }
    }

    override fun getMediaType(): MEDIA_TYPE = MEDIA_TYPE.AUDIO
}

class ResidualJunkScanStep: JunkScanStep<ResidualBean>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startResidualScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelResidualScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.residual_junk)
    override fun onUpdateScan(bean: ResidualBean) {
        val junkChildBean = JunkChildBean()
        junkChildBean.path = bean.path
        junkChildBean.size = bean.size
        junkChildBean.name = bean.desc
        junkBean.addChildBean(junkChildBean)
        junkBean.size += junkChildBean.size
    }
}

class TmpJunkScanStep: JunkScanStep<TmpBean>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startTmpScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelTmpScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.tmp_junk)
    override fun onUpdateScan(bean: TmpBean) {
        val junkChildBean = JunkChildBean()
        junkChildBean.path = bean.path
        junkChildBean.size = bean.size
        junkChildBean.name = bean.name
        junkBean.size += junkChildBean.size
        junkBean.addChildBean(junkChildBean)
    }
}

class LogJunkScanStep: JunkScanStep<LogBean>() {
    override fun startScan(cleanSdk: Clean, callback: JunkScanCallback) {
        cleanSdk.startLogScan(callback)
    }

    override fun cancelScan(cleanSdk: Clean) {
        cleanSdk.cancelLogScan()
    }

    override fun getJunkName(): String = StringUtils.getString(R.string.log_junk)
    override fun onUpdateScan(bean: LogBean) {
        val junkChildBean = JunkChildBean()
        junkChildBean.path = bean.path
        junkChildBean.size = bean.size
        junkChildBean.name = bean.name
        junkBean.size += junkChildBean.size
        junkBean.addChildBean(junkChildBean)
    }
}